package com.lry.jvm.rtda.heap;

import com.lry.jvm.classfile.constantpool.ConstantMemberRefInfo;
import com.lry.jvm.util.Util;

public class InterfaceMethodRef extends MemberRef {

    private JMethod method;

    public InterfaceMethodRef(RuntimeConstantPool rcp, ConstantMemberRefInfo memberRefInfo) {
        super(memberRefInfo);
        this.setRcp(rcp);
    }

    public JMethod resolvedInterfaceMethod(){
        if(null==method){
            resolveInterfaceMethodRef();
        }
        return method;
    }

    private void resolveInterfaceMethodRef() {
        JClass d = getRcp().getJClass();
        JClass c = resolvedClass();
        if(!c.isInterface()){
            Util.panic("java.lang.IncompatibleClassChangeError");
        }

        JMethod lkMethod = lookupInterfaceMethod(c,getName(),getDescriptor());

        if (lkMethod == null) {
            Util.panic("java.lang.NoSuchMethodError");
        }
        if (!lkMethod.isAccessibleTo(d)) {
            Util.panic("java.lang.IllegalAccessError");
        }
        method = lkMethod;

    }

    private JMethod lookupInterfaceMethod(JClass c, String name, String descriptor) {
        for(JMethod method:c.getMethods()){
            if(name.equals(method.getName())&&descriptor.equals(method.getDescriptor())){
                return method;
            }
        }

        return MethodLookup.lookupMethodInInterfaces(c.getInterfaces(),name,descriptor);
    }
}
